#include "BrushCommon.h"
#include "Character/monster/MonsterMgr.h"
#include "Character/monster/MonsterRefCfg.h"
#include "Duplicate/IDuplicate.h"
#include "Character/CreatureMgr.h"
#include "Character/newAI/behaviac/CreatureCommonAI.h"

BrushCommon::BrushCommon() :m_pDuplicate(nullptr), m_pBrush(nullptr)
{
	m_bBrushFinish = false;
	m_bStart = false;
	m_setEnterAreaFight.clear();
}

BrushCommon::~BrushCommon()
{
	
}

bool BrushCommon::Init(IDuplicate *pDuplicate)
{
	if (nullptr == pDuplicate)
	{
		LogErrFmtPrint("BrushCommon::Init...nullptr == pDuplicate");
		return false;
	}
	m_pDuplicate = pDuplicate;
	AllBrushDataCfg *pAllBrush = m_pDuplicate->GetBrushData();
	if (nullptr == pAllBrush)
	{
		LogErrFmtPrint("BrushCommon::Init...nullptr == pAllBrush...sceneid:%u,dupid:%u ",pDuplicate->GetSceneID(),pDuplicate->GetDuplicateID());
		return false;
	}
	m_pBrush = &pAllBrush->stCommon;
	return true;
}

void BrushCommon::UnInit()
{
	g_GetTimerAxis()->KillAllTimer(this);
	m_pDuplicate = nullptr;
	m_pBrush = nullptr;
	m_bStart = false;
	m_bBrushFinish = false;
	m_setEnterAreaFight.clear();
}
void BrushCommon::StartBrush()
{
	m_bStart = true;
	InitTimeBrush();
}

void BrushCommon::StopBrush()
{
	m_bStart = false;
	m_bBrushFinish = true;
	g_GetTimerAxis()->KillAllTimer(this);
}

//是否刷怪完成
bool BrushCommon::FinishBrush()
{
	return m_bBrushFinish;
}

void BrushCommon::BrushUpdate()
{
	if (m_bBrushFinish)
		return;
	CheckMonsEnterArea();
	if (m_pBrush->brushFinish())
		m_bBrushFinish = true;
}

void BrushCommon::OnTimer(uint32_t nTimerID)
{
	TimeBrush(nTimerID);
}

void BrushCommon::OnMonterDead(uint64_t monsCid, uint32_t monsId, uint32_t count, int32_t formationId, uint64_t killerCid)
{
	if (nullptr == m_pBrush)
	{
		LogErrFmtPrint("[logic] BrushCommon::OnMonterDead....nullptr == m_pBrush....monsCid:%lu, monsId:%u, count:%u, formationId:%u,killercid:%lu ", monsCid, monsId, count, formationId,killerCid);
		return;
	}
	if (nullptr == m_pDuplicate)
	{
		LogErrFmtPrint("[logic] BrushCommon::OnMonterDead....nullptr == m_pDuplicate....monsCid:%lu, monsId:%u, count:%u, formationId:%u,killercid:%lu ", monsCid, monsId, count, formationId, killerCid);
		return;
	}
	//LogDebugFmtPrint("[logic] BrushCommon::OnMonterDead....monsCid:%lu, monsId:%u, count:%u, formationId:%u ",monsCid, monsId,count,formationId);
	//是否是编队怪，是否有死亡刷新
	if (formationId > 0)
	{
		//有编队的怪
		VecDieBrushCfg::iterator iterDie = m_pBrush->vecDieBrush.begin();
		while (iterDie != m_pBrush->vecDieBrush.end())
		{
			DieBrushCfgInfo &stDieCfg = (*iterDie);
			if (0 == stDieCfg.setDie.size())
			{
				iterDie = m_pBrush->vecDieBrush.erase(iterDie);
				continue;
			}
			SET_UINT32::iterator iterSet = stDieCfg.setDie.find(formationId);
			if (iterSet == stDieCfg.setDie.end())
			{
				++iterDie;
				continue;
			}
			MAP_UINT32_UINT32::iterator iterMon = stDieCfg.mapDieMonster.find(monsId);
			if (iterMon == stDieCfg.mapDieMonster.end())
			{
				++iterDie;
				continue;
			}
			if (iterMon->second >= count)
			{
				iterMon->second -= count;
			}
			else
			{
				iterMon->second = 0;
			}
			//
			if (iterMon->second > 0)
			{
				++iterDie;
				continue;
			}
			stDieCfg.mapDieMonster.erase(iterMon);
			if (stDieCfg.mapDieMonster.size() > 0)
			{
				++iterDie;
				continue;
			}
			////所有指定编队的怪物全部死亡了,刷新另外指定编队的怪物
			SET_UINT32::iterator iterBrush = stDieCfg.setBrush.begin();
			for (; iterBrush != stDieCfg.setBrush.end(); ++iterBrush)
			{
				uint32_t tmp_formationId = (*iterBrush);
				const std::vector<MonsterRefLocation> *pRefLoc = g_GetMapLocationCfg()->GetMapGroupMonster(m_pDuplicate->GetMapID(), tmp_formationId);
				if (nullptr != pRefLoc)
				{
					std::vector<MonsterRefLocation>::const_iterator iterNew = pRefLoc->begin();
					for (; iterNew != pRefLoc->end(); ++iterNew)
					{
						const MonsterRefLocation &ref = (*iterNew);

						Point3<float> curDir = Point3<float>(0,0,1);
						if (ref.m_dir != Point3<float>())
						{
							float rad = AngleToRadian(ref.m_dir.y);
							float x = sin(rad);
							float z = cos(rad);
							Point3<float> dir = Point3<float>(x,0, z);
							float length = dir.length();
							if (length != 0)
							{
								curDir = dir/ length;
							}
						}
						MonsCreateParam createParam;
						createParam.createType = EMonsCreateType_Dup;
						createParam.createTypeVal = m_pDuplicate->GetDuplicateID();
						Monster *pMonster = g_GetCreatureMgr()->CreateMonster(ref.m_id, m_pDuplicate->GetSceneID(), ref.m_bornPos, createParam, curDir, ref.m_RefLocIndex, nullptr, 0, ref.m_group);
						if (nullptr != pMonster)
						{
							pMonster->SetFormationId(tmp_formationId);

							//
							LogDebugFmtPrint("[logic] BrushCommon::OnMonterDead....monsId:%u, count:%u, formationId:%u, brush_mon_id:%u, brush_tid:%u ", monsId, count, formationId, ref.m_id, tmp_formationId);
						}
					}
				}
			} // end of for (; iterBrush != stDieCfg.setBrush.end(); ++iterBrush)

			iterDie = m_pBrush->vecDieBrush.erase(iterDie);
		}
	}
	else
	{
		MAP_UINT32_UINT32::iterator iter = m_pBrush->mapAllTimeMonster.find(monsId);
		if (iter != m_pBrush->mapAllTimeMonster.end())
		{
			if (iter->second >= count)
			{
				iter->second -= count;
			}
			else
			{
				iter->second = 0;
			}

			if (iter->second == 0)
			{
				m_pBrush->mapAllTimeMonster.erase(iter);
			}
		}
	}
}

//区域刷怪
bool BrushCommon::EnterAreaBrush(uint32_t areaId)
{
	if (nullptr == m_pBrush)
	{
		LogErrFmtPrint("[logic] BrushCommon::EnterAreaBrush....nullptr == m_pBrush....areaId:%u , dupid:%u, sceneid:%u ", areaId, m_pDuplicate->GetDuplicateID(), m_pDuplicate->GetSceneID());
		return false;
	}
	if (nullptr == m_pDuplicate)
	{
		LogErrFmtPrint("[logic] BrushCommon::EnterAreaBrush....nullptr == m_pDuplicate....areaId:%u , dupid:%u, sceneid:%u ", areaId, m_pDuplicate->GetDuplicateID(), m_pDuplicate->GetSceneID());
		return false;
	}
	LogDebugFmtPrint("[logic] BrushCommon::EnterAreaBrush....areaId:%u , dupid:%u, sceneid:%u ", areaId, m_pDuplicate->GetDuplicateID(), m_pDuplicate->GetSceneID());
	MAP_UINT32_VEC_UINT32::iterator iter = m_pBrush->mapVecEnterArea.find(areaId);
	if (iter == m_pBrush->mapVecEnterArea.end())
	{
		return false;
	}
	VEC_UINT32 &vecBrushTid = iter->second;
	VEC_UINT32::iterator iterTid = vecBrushTid.begin();
	for (; iterTid != vecBrushTid.end(); ++iterTid)
	{
		//这里按照怪物编队ID刷怪
		uint32_t nGroupId = (*iterTid);
		const std::vector<MonsterRefLocation>* pMonsterRefCfg = g_GetMapLocationCfg()->GetMapGroupMonster(m_pDuplicate->GetMapID(), nGroupId);
		if (nullptr == pMonsterRefCfg)
		{
			continue;
		}
		std::vector<MonsterRefLocation>::const_iterator iterRef = pMonsterRefCfg->begin();
		for (; iterRef != pMonsterRefCfg->end(); ++iterRef)
		{
			const MonsterRefLocation &stMonCfg = (*iterRef);
			Point3<float> curDir = Point3<float>(0,0,1);
			if (stMonCfg.m_dir != Point3<float>())
			{
				float rad = AngleToRadian(stMonCfg.m_dir.y);
				float x = sin(rad);
				float z = cos(rad);
				Point3<float> dir = Point3<float>(x,0, z);
				float length = dir.length();
				if (length != 0)
				{
					curDir = dir/ length;
				}
			}
			MonsCreateParam createParam;
			createParam.createType = EMonsCreateType_Dup;
			createParam.createTypeVal = m_pDuplicate->GetDuplicateID();
			Monster *pMonster = g_GetCreatureMgr()->CreateMonster(stMonCfg.m_id, m_pDuplicate->GetSceneID(), stMonCfg.m_bornPos, createParam,curDir, stMonCfg.m_RefLocIndex, nullptr, 0, stMonCfg.m_group);
			if (nullptr != pMonster)
			{
				//设置编队
				pMonster->SetFormationId(nGroupId);

				LogDebugFmtPrint("[logic] BrushCommon::EnterAreaBrush....areaId:%u ,nGroupId:%u,monsid:%u,cid:%llu, dupid:%u, sceneid:%u ", areaId, nGroupId, stMonCfg.m_id,pMonster->GetCid(), m_pDuplicate->GetDuplicateID(), m_pDuplicate->GetSceneID());
			}
		}
	} // end of for (; iterTid != vecBrushTid.end(); ++iterTid)

	m_pBrush->mapVecEnterArea.erase(iter);

	return true;
}

//获取刷怪定时器ID
int32_t BrushCommon::GetTidByIdx(int32_t idx1, int32_t idx2, int32_t idx3)
{
	int32_t tid = 0;
	unsigned char *p = (unsigned char*)&tid;
	*p = idx1;
	*(p + 1) = idx2;
	*(p + 2) = idx3;
	return tid;
}
//获取索引
void BrushCommon::GetIdxByTid(int32_t tid, int32_t &idx1, int32_t &idx2, int32_t &idx3)
{
	unsigned char *p = (unsigned char*)&tid;
	idx1 = *p;
	idx2 = *(p + 1);
	idx3 = *(p + 2);
}

//初始化定时刷怪
void BrushCommon::InitTimeBrush()
{
	if (nullptr == m_pBrush)
	{
		LogErrFmtPrint("BrushCommon::InitTimeBrush....nullptr == m_pBrush...");
		return;
	}
	/*
	大组索引，小组索引，子项索引 每个索引1个字节
	*/
	VecAllTimeBrushDataCfg::iterator iter = m_pBrush->vecAllTimeBrush.begin();
	int32_t nAllGroupCnt = m_pBrush->vecAllTimeBrush.size();
	for (int32_t i = 0; i < nAllGroupCnt; ++i)
	{
		TimeBrushDataCfg &stFix = m_pBrush->vecAllTimeBrush.at(i);
		int32_t nGroupCnt = stFix.vecTimeGroupCfg.size();
		if (nGroupCnt > 0)
		{
			int32_t idx = 0;
			VecTimeBrushCfg &vecLevMons = stFix.vecTimeGroupCfg.at(idx);
			int32_t nSubCnt = vecLevMons.size();
			for (int32_t j = 0; j < nSubCnt; ++j)
			{
				//LevelMonsCfgInfo &stMons = vecLevMons.at(j);
				int32_t idx1 = i + 1;  //大组索引
				int32_t idx2 = idx + 1; //小组索引
				int32_t idx3 = j + 1;  //子项索引
				int32_t nTimerID = GetTidByIdx(idx1, idx2, idx3);
				LogDebugFmtPrint("[logic] CommonBrush::InitTimeBrush...nTimerID:%d ,idx1:%d,idx2:%d, idx3:%d ", nTimerID, idx1, idx2, idx3);
				int32_t nInitDelay = ((stFix.nInitDelay == 0) ? 500 : stFix.nInitDelay * 1000);
				g_GetTimerAxis()->SetTimer(nTimerID, nInitDelay, this, 1);
			}
		}
	}
}
//定时刷怪
void BrushCommon::TimeBrush(int32_t nTimerID)
{
	if (m_bBrushFinish)
	{
		return;
	}
	if (nullptr == m_pBrush)
	{
		LogErrFmtPrint("BrushCommon::TimeBrush...nullptr == m_pBrush...timerid:%d ", nTimerID);
		return;
	}
	if (nullptr == m_pDuplicate)
	{
		LogErrFmtPrint("BrushCommon::TimeBrush...nullptr == m_pDuplicate...timerid:%d ", nTimerID);
		return;
	}
	int32_t idx1 = 0;
	int32_t idx2 = 0;
	int32_t idx3 = 0;
	GetIdxByTid(nTimerID, idx1, idx2, idx3);
	int32_t new_idx1 = idx1;
	int32_t new_idx2 = idx2;
	int32_t new_idx3 = idx3;
	idx1 -= 1; //大组索引
	idx2 -= 1; //小组索引
	idx3 -= 1; //子项索引
	if (idx1 < 0 || idx2 < 0 || idx3 < 0)
	{
		return;
	}
	if ((uint32_t)idx1 >= m_pBrush->vecAllTimeBrush.size())
	{
		return;
	}
	TimeBrushDataCfg &stBrush = m_pBrush->vecAllTimeBrush.at(idx1);
	if ((uint32_t)idx2 >= stBrush.vecTimeGroupCfg.size())
	{
		return;
	}
	VecTimeBrushCfg &vecLevMon = stBrush.vecTimeGroupCfg.at(idx2);
	if ((uint32_t)idx3 >= vecLevMon.size())
	{
		return;
	}
	TimeBrushCfgInfo &stMons = vecLevMon.at(idx3);
	if (stMons.nNum > 0)
	{
		//这里创建怪物
		//LogDebugFmtPrint("[logic] TimeBrush...duplicateid:%u,sceneid:%u,monsid:%u,[%f,%f,%f] ..", m_nDuplicateID, m_nSceneID, stMons.nMonsID, stMons.xpos, stMons.ypos, stMons.zpos);
		Point3<float> pos = g_GetMapLocationCfg()->RandPosInArea(stMons.nAreaID);
		MonsCreateParam createParam;
		createParam.createType = EMonsCreateType_Dup;
		createParam.createTypeVal = m_pDuplicate->GetDuplicateID();
		Monster *pMonster = g_GetCreatureMgr()->CreateMonster(stMons.nMonsID, m_pDuplicate->GetSceneID(), pos, createParam);
		if (nullptr != pMonster)
		{
			LogDebugFmtPrint("[logic] BrushCommon::TimeBrush...duplicateid:%u,sceneid:%u ,  monsid:%u,[%f,%f,%f] , [%d,%d,%d ] ..", m_pDuplicate->GetDuplicateID(), m_pDuplicate->GetSceneID(),  stMons.nMonsID, pos.x, pos.y, pos.z, new_idx1, new_idx2, new_idx3);
		}
		else
		{
			LogErrFmtPrint("[logic] BrushCommon::TimeBrush error...duplicateid:%u,sceneid:%u , areaid:%u,  monsid:%u,[%f,%f,%f] , [%d,%d,%d ] ..", m_pDuplicate->GetDuplicateID(), m_pDuplicate->GetSceneID(), stMons.nAreaID, stMons.nMonsID, pos.x, pos.y, pos.z, new_idx1, new_idx2, new_idx3);
		}
		
		//数量减1
		stMons.nNum -= 1;
		if (stMons.nNum > 0)
		{
			//设置下一次刷新的定时器
			int32_t nBornDelay = ((stMons.nBornDelay == 0) ? 500 : stMons.nBornDelay * 1000);
			g_GetTimerAxis()->KillTimer(nTimerID, this);
			g_GetTimerAxis()->SetTimer(nTimerID, nBornDelay, this, 1);
		}
		else
		{
			/*if (CheckFixTimeBrushFinish())
			{
			//怪物已刷完
			m_bFinishBrush = true;
			return;

			}*/
			if ((uint32_t)idx2 < stBrush.vecTimeGroupCfg.size() - 1)
			{
				//小组索引如果不是最后一个，检测当前小组怪物列表是否已经全部刷完
				//如果刷完了，需要刷下一个小组列表的怪物
				bool bFlag = true;
				VecTimeBrushCfg::iterator iterCheck = vecLevMon.begin();
				for (; iterCheck != vecLevMon.end(); ++iterCheck)
				{
					TimeBrushCfgInfo &stOld = (*iterCheck);
					if (stOld.nNum > 0)
					{
						bFlag = false;
						break;
					}
				}
				if (bFlag)
				{
					//
					int32_t ex_idx2 = idx2 + 1;
					new_idx2 = ex_idx2 + 1;
					//新的小组怪物列表
					VecTimeBrushCfg &vecNewLevMon = stBrush.vecTimeGroupCfg.at(ex_idx2);
					int32_t ex_len = vecNewLevMon.size();
					for (int32_t k = 0; k < ex_len; ++k)
					{
						new_idx3 = k + 1;
						int32_t nNewTimerID = GetTidByIdx(new_idx1, new_idx2, new_idx3);
						int32_t nInter = ((stBrush.nInterSec == 0) ? 500 : stBrush.nInterSec * 1000);
						//设置新的小组开始刷怪的定时器
						g_GetTimerAxis()->KillTimer(nNewTimerID, this);
						g_GetTimerAxis()->SetTimer(nNewTimerID, nInter, this, 1);
					}
				}
			} // end of if (idx2 < stBrush.vecGroupMonsCfg.size() - 1)
		}
	}
}



void BrushCommon::CheckMonsEnterArea()
{
	if (nullptr == m_pDuplicate || nullptr == m_pBrush || !m_bStart || m_bBrushFinish)
	{
		return;
	}
	MonsEnterAreaCfgData &stMonsEnterArea = m_pBrush->stMonsEnterArea;
	if (stMonsEnterArea.mapMonsEnterAreaBrush.size() <= 0 && stMonsEnterArea.vecMonsEnterAreaFight.size() <= 0)
	{
		return;
	}
	uint32_t sceneId = m_pDuplicate->GetSceneID();
	uint32_t mapId = m_pDuplicate->GetMapID();
	uint32_t dupId = m_pDuplicate->GetDuplicateID();
	Scene *pScene = g_GetSceneMgr()->GetScene(sceneId);
	if (nullptr == pScene)
	{
		LogErrFmtPrint("[logic] BrushCommon::CheckMonsEnterArea...nullptr == pScene...sceneid:%u ",sceneId);
		return;
	}
	//校验走进区域该改变战斗方式
	VecMonsEnterAreaFightCfg::iterator iterFight = stMonsEnterArea.vecMonsEnterAreaFight.begin();
	for (; iterFight != stMonsEnterArea.vecMonsEnterAreaFight.end(); ++iterFight)
	{
		MonsEnterAreaFightCfgInfo &fightInfo = (*iterFight);
		MAP_UINT32_SET_UINT64 mapGroupMons;
		mapGroupMons.clear();
		m_pDuplicate->GetMonsByGroup(fightInfo.setMonsTid, mapGroupMons);
		MAP_UINT32_SET_UINT64::iterator iter = mapGroupMons.begin();
		for (; iter != mapGroupMons.end(); ++iter)
		{
			SET_UINT64 &setMons = iter->second;
			SET_UINT64::iterator iterMons = setMons.begin();
			for (; iterMons != setMons.end(); ++iterMons)
			{
				uint64_t monsCid = (*iterMons);
				Monster *pMonster = pScene->GetMonster(monsCid);
				if (nullptr == pMonster)
				{
					m_setEnterAreaFight.insert(monsCid);
					continue;
				}
				SET_UINT64::iterator iterAlreday = m_setEnterAreaFight.find(monsCid);
				if (iterAlreday != m_setEnterAreaFight.end())
				{
					continue;
				}
				uint32_t cfgId = pMonster->GetConfigId();
				uint32_t groupId = pMonster->GetFormationId();
				Point3<float> pos = pMonster->GetPos();
				if (pScene->InArea(fightInfo.areaId, pos))
				{
					LogDebugFmtPrint("[logic] BrushCommon::CheckMonsEnterArea....enter area change fight,dupid:%u,sceneid:%u, monsid:%u, monscid:%lu,groupid:%u, areaid:%u,tofight:%d  ", dupId, sceneId, cfgId, monsCid, groupId, fightInfo.areaId,fightInfo.toFightType);
					m_setEnterAreaFight.insert(monsCid);
					//进去区域了，改变战斗方式
					CreatureCommonAI *pAi = pMonster->GetAiData();
					if (nullptr != pAi)
					{
						pAi->SetAttackType(fightInfo.toFightType);
					}
				}
			}
		}
	}

	//进入区域刷怪
	SET_UINT32 setDelBrush;
	setDelBrush.clear();
	MapMonsEnterAreaBrushCfg::iterator iterBrush = stMonsEnterArea.mapMonsEnterAreaBrush.begin();
	for (; iterBrush != stMonsEnterArea.mapMonsEnterAreaBrush.end(); ++iterBrush)
	{
		MonsEnterAreaBrushCfgInfo &brushInfo = iterBrush->second;
		Monster *pMonster = pScene->GetMonsterByCfgId(brushInfo.monsId);
		if (nullptr == pMonster)
		{
			continue;
		}

		Point3<float> pos = pMonster->GetPos();
		if (!pScene->InArea(brushInfo.areaId, pos))
		{
			continue;
		}
		setDelBrush.insert(brushInfo.monsId);
		//刷新怪物
		SET_INT32::iterator iterTid = brushInfo.setTid.begin();
		for (; iterTid != brushInfo.setTid.end(); ++iterTid)
		{
			uint32_t tid = (*iterTid);
			const std::vector<MonsterRefLocation>* pVecMonsRefLoc = g_GetMapLocationCfg()->GetMapGroupMonster(mapId, tid);
			if (nullptr == pVecMonsRefLoc)
			{
				continue;
			}
			//
			std::vector<MonsterRefLocation>::const_iterator iterLoc = pVecMonsRefLoc->begin();
			for (; iterLoc != pVecMonsRefLoc->end(); ++iterLoc)
			{
				const MonsterRefLocation &refLoc = (*iterLoc);
				Point3<float> dir(0, 0, 1);
				MonsCreateParam createParam;
				createParam.createType = EMonsCreateType_Dup;
				createParam.createTypeVal = m_pDuplicate->GetDuplicateID();
				Monster *pNewMonster = g_GetCreatureMgr()->CreateMonster(refLoc.m_id, sceneId, refLoc.m_bornPos, createParam, dir, refLoc.m_RefLocIndex, nullptr, 0, refLoc.m_group);
				if (nullptr != pNewMonster)
				{
					pNewMonster->SetFormationId(refLoc.m_group);
					LogDebugFmtPrint("[logic] BrushCommon::CheckMonsEnterArea...dupid:%u, sceneid:%u, mapid:%u, monsid:%u,,monsCid:%lu, pos:%f,%f,%f ", dupId, sceneId, mapId, refLoc.m_id, pNewMonster->GetCid(), refLoc.m_bornPos.x, refLoc.m_bornPos.y, refLoc.m_bornPos.z);
				}
				else
				{
					LogErrFmtPrint("[logic] BrushCommon::CheckMonsEnterArea....nullptr == pNewMonster...dupid:%u, sceneid:%u, mapid:%u, monsid:%u, pos:%f,%f,%f ", dupId, sceneId, mapId, refLoc.m_id, refLoc.m_bornPos.x, refLoc.m_bornPos.y, refLoc.m_bornPos.z);
				}
			}
		}
	}
	SET_UINT32::iterator iterDel = setDelBrush.begin();
	for (; iterDel != setDelBrush.end(); ++iterDel)
	{
		stMonsEnterArea.mapMonsEnterAreaBrush.erase((*iterDel));
	}
}
